package com.platform.comm.service.impl;

import com.google.common.collect.Lists;
import com.platform.comm.service.CommonBiz;
import com.querydsl.core.Tuple;
import com.querydsl.core.types.Expression;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.JPQLQuery;
import com.platform.comm.repository.CustomBaseRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

import javax.persistence.EntityNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.function.Consumer;

/**
 * Common business interface implementation
 * @author coder
 */
public class CommonBizImpl<R extends CustomBaseRepository<T, ID>, T, ID> implements CommonBiz<T, ID> {
    protected final R repository;

    public CommonBizImpl(R baseRepository) {
        this.repository = baseRepository;
    }

    @Override
    public T saveEntity(T entity) {
        return repository.save(entity);
    }

    @Override
    public List<T> saveAllEntity(List<T> entitys) {
        return repository.saveAll(entitys);
    }

    @Override
    public Optional<T> queryById(ID id) {
        return repository.findById(id);
    }

    @Override
    public T fetchById(ID id) {
        Optional<T> optional = repository.findById(id);
        return optional.orElseThrow(() -> new EntityNotFoundException("未能查询到记录"));
    }

    @Override
    public Optional<T> queryOne(Predicate predicate) {
        return repository.findOne(predicate);
    }

    @Override
    public Optional<Tuple> queryOne(Predicate predicate, Expression<?>... expressions) {
        return repository.findOne(predicate, expressions);
    }

    @Override
    public T fetchOne(Predicate predicate) {
        return repository.findOne(predicate).orElseThrow(EntityNotFoundException::new);
    }

    @Override
    public Tuple fetchOne(Predicate predicate, Expression<?>... expressions) {
        return repository.findOne(predicate, expressions).orElseThrow(NoSuchElementException::new);
    }

    @Override
    public T fetchOne(Predicate predicate, Consumer<JPQLQuery<?>> consumer) {
        Optional<T> optional = repository.findOne(predicate, consumer);
        return optional.orElseThrow(EntityNotFoundException::new);
    }

    @Override
    public T getOne(Predicate predicate) {
        return repository.findOne(predicate).orElse(null);
    }

    @Override
    public List<T> queryAll(Predicate predicate) {
        Iterable<T> iterable = repository.findAll(predicate);
        List<T> list = new ArrayList<>();
        iterable.forEach(list::add);
        return list;
    }

    @Override
    public Page<T> queryByPage(Predicate predicate, Pageable pageable) {
        return repository.findAll(predicate, pageable);
    }

    @Override
    public Page<T> queryByPage(Predicate predicate, Pageable pageable, Consumer<JPQLQuery<?>> consumer) {
        return repository.findAll(predicate, pageable, consumer);
    }

    @Override
    public List<T> queryAll(Predicate predicate, OrderSpecifier... orderSpecifiers) {
        return Lists.newArrayList(repository.findAll(predicate, orderSpecifiers));
    }

    @Override
    public List<T> queryAll(Predicate predicate, Sort sort) {
        Iterable<T> iterable = repository.findAll(predicate, sort);
        return Lists.newArrayList(iterable);
    }

    @Override
    public long count(Predicate predicate) {
        return repository.count(predicate);
    }

    @Override
    public void removeById(ID id) {
        repository.deleteById(id);
    }

    @Override
    public void deleteAndFlush(T entity) {
        repository.delete(entity);
        repository.flush();
    }

    @Override
    public void flush() {
        repository.flush();
    }
}
